<?php

namespace Kangcg\Application\Security;

use Kangcg\Application\Helper\HelperFunc;

/**
 * Class Openssl
 * @package Kang\Libs\Helper\Security
 */
class Openssl implements SecurityInterface
{
    /**
     * @param array $config
     * @param string key 密匙
     * @param string iv 必须16位
     * @param string method aes-256-cbc
     * @param int option //补位方式  OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING.
     */
    public function __construct(array $config)
    {
        $this->init($config);
    }

    /**
     * 要加密的字符
     * @param string | array $encrypted
     * @return bool|false|string
     */
    public function encode($encrypted, bool $isUsePublic = false)
    {
        try {
            $encrypted = is_array($encrypted) ? json_encode($encrypted, JSON_UNESCAPED_UNICODE) : $encrypted;
            $encrypted = openssl_encrypt($encrypted, $this->_config['method'], $this->_config['key'], $this->_config['option'], $this->_config['iv']);
            return base64_encode($encrypted);
        } catch (\Exception $exception) {
            return $this->setError($exception->getMessage());
        }
    }

    /**
     * 获取解密结果
     * @param string $encrypted
     * @return bool|false|string
     */
    public function decode(string $encrypted, $isUsePublic = true)
    {
        try {
            $encrypted = base64_decode($encrypted);
            return openssl_decrypt($encrypted, $this->_config['method'], $this->_config['key'], $this->_config['option'], $this->_config['iv']);
        } catch (\Exception $exception) {
            return $this->setError($exception->getMessage());
        }
    }

    public function sign(string $str)
    {
        return md5($str);
    }

    /**
     * @return string
     */
    public function getEncryption(): string
    {
        return 'aes';
    }

    /**
     * @param null $key
     * @return array|mixed|string
     */
    public function getConfig($key = null)
    {
        return $key === null ? $this->_config : ($this->_config[$key] ?? '');
    }

    /**
     * @param array $config
     * @param string key 密匙
     * @param string iv 必须16位
     * @param string method
     * @param int option //补位方式  OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING.
     * @return Openssl
     */
    public static function getInstall(array $config)
    {
        if (self::$_install === null) {
            self::$_install = new self($config);
        }

        return self::$_install;
    }

    /**
     * @param array $config
     * @param string key 密匙
     * @param string iv 必须16位
     * @param string method aes-256-cbc
     * @param int option //补位方式  OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING.
     * @return $this
     */
    public function init(array $config)
    {
        $key = md5($config['key']);
        $this->_config['key'] = substr($key, 16);
        $this->_config['iv'] = HelperFunc::stringConstPadding($key, 16);
        $this->_config['method'] = $config['method'] ?? 'AES-128-CBC';
        $this->_config['option'] = $config['option'] ?? 0;
        return $this;
    }

    private function setError($error)
    {
        $this->_error = $error;
        return false;
    }

    public function getError()
    {
        return $this->_error;
    }

    private $_error = null;
    private $_config = null;
    private static $_install = null;
}
